# dbplugs/todo.py
#
#

""" provides todo related commands """

__copyright__ = 'this file is in the public domain'

from gozerbot.generic import strtotime, striptime, getwho, today
from gozerbot.commands import cmnds
from gozerbot.examples import examples
from gozerbot.users import users
from gozerbot.aliases import aliases
from gozerbot.plughelp import plughelp
from gozerbot.db import db
import time

plughelp.add('todo', 'manage todo lists .. by user or by channel')

class Todo(object):

    """ database todo interface """

    def size(self):
        result = db.execute(""" SELECT COUNT(*) FROM todo """)
        return result[0][0]
        
    def get(self, name):
        """ get todo list of <name> """
        name = name.lower()
        result = db.execute(""" SELECT * FROM todo WHERE name = %s ORDER BY \
priority DESC""", name)
        return result

    def getid(self, idnr):
        """ get todo data of <idnr> """
        result = db.execute(""" SELECT * FROM todo WHERE indx = %s """, idnr)
        return result

    def setprio(self, todonr, prio):
        """ set priority of todonr """
        result = db.execute(""" UPDATE todo SET priority = %s WHERE indx \
= %s """, (prio, todonr))
        return result

    def getprio(self, todonr):
        """ get priority of todonr """
        result = db.execute(""" SELECT * FROM todo WHERE indx = %s """, todonr)
        return result

    def add(self, name, txt, ttime):
        """ add a todo """
        name = name.lower()
        txt = txt.strip()
        if ttime:
            result = db.execute(""" INSERT INTO todo(name, time, \
descr) VALUES (%s, %s, %s) """, (name, ttime, txt))
        else:
            result = db.execute(""" INSERT INTO todo(name, descr) \
VALUES (%s, %s) """, (name, txt))
        return result

    def delete(self, name, indexnr):
        """ delete todo item """
        name = name.lower()
        result = db.execute(""" DELETE FROM todo WHERE name = %s AND \
indx = %s """, (name, indexnr))
        return result

    def toolate(self, name):
        """ show if there are any time related todoos that are too late """
        name = name.lower()
        now = time.time()
        result = db.execute(""" SELECT * FROM todo WHERE name = %s AND \
time < %s """, (name, now))
        return result

    def withintime(self, name, time1, time2):
        """ show todo list within time frame """
        name = name.lower()
        result = db.execute(""" SELECT * FROM todo WHERE name = %s AND \
time > %s AND time < %s """, (name, time1, time2))
        return result

todo = Todo()

def handle_todo(bot, ievent):
    """ todo [<item>] .. show todo list or set todo item """
    if len(ievent.args) > 0:
        handle_todo2(bot, ievent)
        return
    name = users.getname(ievent.userhost)
    result = todo.get(name)
    if not result:
        ievent.reply('nothing todo ;]')
        return
    res = ""
    for i in result:
        if i[6]:
            res += "%s) %s [%s] " % (i[0], i[5], i[6])
        else:
            res += "%s) %s " % (i[0], i[5])
    ievent.reply(res)

def handle_todo2(bot, ievent):
    """ set todo item """
    if not ievent.rest:
        ievent.missing("<what>")
        return
    else:
        what = ievent.rest
    name = users.getname(ievent.userhost)
    ttime = strtotime(what)
    res = 0
    if not ttime  == None:
        ievent.reply('time detected ' + time.ctime(ttime))
        what = striptime(what)
        res = todo.add(name, what, ttime)
    else:
        res = todo.add(name, what, None)
    if res:
        ievent.reply('todo %s added' % res)
    else:
        ievent.reply('add failed')

cmnds.add('todo', handle_todo, 'USER')
examples.add('todo', 'todo [<item>] .. show todo items or add a todo \
item', '1) todo 2) todo program the bot')

def handle_todoshow(bot, ievent):
    """ todo-show <nr> .. show todo item data """
    try:
        todonr = int(ievent.args[0])
    except (IndexError, ValueError):
        ievent.missing("<nr>")
        return
    name = users.getname(ievent.userhost)
    result = todo.get(name)
    nrs = []
    for i in result:
        nrs.append(i[0])
    if todonr not in nrs:
        ievent.reply('%s is not on your todo list' % todonr)
        return
    result = todo.getid(todonr)
    if result:
        res = list(result[0])
        res[2] = time.ctime(res[2])
        ievent.reply("indx: %s name: %s time: %s duration: %s \
warnsec: %s descr: %s priority: %s" % tuple(res))
    else:
        ievent.reply("can't fetch data for %s" % todonr)

cmnds.add('todo-show', handle_todoshow, 'USER')
examples.add('todo-show', 'todo-show <nr> .. show data of todo item', \
'todo-show 10')

def handle_setpriority(bot, ievent):
    """ todo-setprio [<channel|name] <nr> <prio> .. set todo item priority"""
    try:
        (name, todonr, prio) = ievent.args
        todonr = int(todonr)
        prio = int(prio)
    except ValueError:
        try:
            todonr = int(ievent.args[0])
            prio = int(ievent.args[1])
            name = users.getname(ievent.userhost)
        except (ValueError, IndexError):
            ievent.missing("[<channel>] <todnr> <prio>")
            return
    name = name.lower()
    result = todo.getid(todonr)
    if not result:
        ievent.reply("can't find todo for %s" % name)
        return
    if result[0][1] != name:
        ievent.reply('%s is not in your todolist' % todonr)
        return
    if todo.setprio(todonr, prio):
        ievent.reply('priority set')
    else:
        ievent.reply('update of %s failed' % todonr)

cmnds.add('todo-setprio', handle_setpriority, 'USER')
examples.add('todo-setprio', 'todo-setprio [<channel|name>] <nr> <prio> .. \
set todo priority', '1) todo-setprio #dunkbots 2 5 2) todo-setprio 2 10')
aliases.data['setprio'] = 'todo-setprio'

def handle_getpriority(bot, ievent):
    """ todo-prio [<channel|name>] <nr> .. get priority of todo item"""
    try:
        (name, itemnr) = ievent.args
        itemnr = int(itemnr)
    except ValueError:
        try:
            itemnr = int(ievent.args[0])
            name = users.getname(ievent.userhost)
        except (IndexError, ValueError):
            ievent.missing('[<channel|name>] <itemnr>')
            return
    name = name.lower()
    prio = todo.getprio(itemnr)
    if prio: 
        if prio[0][0] != name:
            ievent.reply("todonr %s is not yours" % itemnr)
            return
        if len(prio) == 1:
            ievent.reply("priority is 0")
        else:
            ievent.reply('priority is %s' % prio[0][1])
    else:
        ievent.reply('no priority found for todoitem %s' % itemnr)

cmnds.add('todo-prio', handle_getpriority, 'USER')
examples.add('todo-prio', 'todo-prio [<channel|name>] <nr> .. get todo \
priority', '1) todo-prio #dunkbots 5 2) todo-prio 3')
aliases.data['prio'] = 'todo-prio'

def handle_tododone(bot, ievent):
    """ todo-done <listofnrs> .. remove todo items """
    if len(ievent.args) == 0:
        ievent.missing('<list of nrs>')
        return
    try:
        nrs = []
        for i in ievent.args:
            nrs.append(int(i))
    except ValueError:
        ievent.reply('%s is not an integer' % i)
        return
    name = users.getname(ievent.userhost)
    if not name:
        ievent.reply("can't find name of %s" % ievent.userhost)
        return
    teller = 0
    failed = []
    for i in nrs:
        result = todo.delete(name, i)
        if not result:
            failed.append(str(i))
        else:
            teller += 1
    if failed:
        ievent.reply('failed to delete %s' % ' '.join(failed))
    if teller == 1:
        ievent.reply('1 item deleted')
    elif teller == 0:
        ievent.reply('no items deleted')
    else:
        ievent.reply('%s items deleted' % teller)

cmnds.add('todo-done', handle_tododone, 'USER')
examples.add('todo-done', 'todo-done <listofnrs> .. remove items from todo \
list', '1) todo-done 1 2) todo-done 3 5 8')
aliases.data['done'] = 'todo-done'

def handle_settodo(bot, ievent):
    """ todo-set <nick> <txt> .. add to todo of another user """
    try:
        who = ievent.args[0]
        what = ' '.join(ievent.args[1:])
    except IndexError:
        ievent.missing('<nick> <txt>')
        return
    if not what:
        ievent.missing('<nick> <txt>')
        return
    userhost = getwho(bot, who)
    if not userhost:
        ievent.reply("can't find userhost for %s" % who)
        return
    whoname = users.getname(userhost)
    if not whoname:
        ievent.reply("can't find user for %s" % userhost)
        return
    name = users.getname(ievent.userhost)
    if not users.permitted(userhost, name, 'todo'):
        ievent.reply("%s doesn't permit todo sharing for %s " % \
(whoname, name))
        return
    what = "%s: %s" % (ievent.nick, what)
    ttime = strtotime(what)
    if not ttime  == None:
        ievent.reply('time detected ' + time.ctime(ttime))
        what = striptime(what)
        result = todo.add(whoname, what, ttime)
    else:
        result = todo.add(whoname, what, None)
    if result:
        ievent.reply('todo %s added' % result)
    else:
        ievent.reply('add failed')

cmnds.add('todo-set', handle_settodo, 'USER')
examples.add('todo-set', 'todo-set <nick> <txt> .. set todo item of \
<nick>', 'todo-set dunker bot proggen')

def handle_gettodo(bot, ievent):
    """ todo-get <nick> .. get todo of other user """
    try:
        who = ievent.args[0]
    except IndexError:
        ievent.missing('<nick>')
        return
    userhost = getwho(bot, who)
    if not userhost:
        ievent.reply("can't find userhost for %s" % who)
        return
    whoname = users.getname(userhost)
    if not whoname:
        ievent.reply("can't find user for %s" % userhost)
        return
    name = users.getname(ievent.userhost)
    if not users.permitted(userhost, name, 'todo'):
        ievent.reply("%s doesn't permit todo sharing for %s " % \
(who, name))
        return
    result = todo.get(whoname)
    if result:
        res = ""
        for i in result:
            res += "%s) %s " % (i[0], i[5])
        ievent.reply(res)
    else:
        ievent.reply('%s has nothing todo' % who)

cmnds.add('todo-get', handle_gettodo, ['USER', 'WEB'])
examples.add('todo-get', 'todo-get <nick> .. get the todo list of \
<nick>', 'todo-get dunker')

def handle_chantodo(bot, ievent):
    """ todo-chan [<txt>] .. show todoos or set todo item for channel"""
    if ievent.rest:
        handle_chantodo2(bot, ievent)
        return
    saytodo(bot, ievent, ievent.channel)

def handle_chantodo2(bot, ievent):
    """ set todo item for channel"""
    what = ievent.rest
    ttime = strtotime(what)
    if not ttime  == None:
        ievent.reply('time detected ' + time.ctime(ttime))
        result = '(%s) ' % ievent.nick + striptime(what)
        todo.add(ievent.channel, result, ttime)
    else:
        result = '(%s) ' % ievent.nick + what
        todo.add(ievent.channel, result, None)
    ievent.reply('todo item added')

cmnds.add('todo-chan', handle_chantodo, 'USER')
examples.add('todo-chan', 'todo-chan [<txt>] .. add channel todo or show \
channel todoos', '1) todo-chan 2) todo-chan fix bla')
aliases.data['chantodo'] = 'todo-chan'

def handle_chandone(bot, ievent):
    """ todo-chandone <listofnrs> .. remove channel todo item """
    if not ievent.rest:
        ievent.missing('<listofnrs>')
        return
    data = ievent.rest.split()
    try:
        nrs = []
        for i in data:
            nrs.append(int(i))
    except ValueError:
        ievent.reply('%s is not an integer' % i)
        return
    teller = 0
    for i in nrs:
        result = todo.delete(ievent.channel, i)
        if result:
            teller += 1
    if teller == 1:
        ievent.reply('1 item deleted')
    elif teller == 0:
        ievent.reply('no items deleted')
    else:
        ievent.reply('%s items deleted' % teller)

cmnds.add('todo-chandone', handle_chandone, 'USER')
examples.add('todo-chandone', 'todo-chandone <listofnrs> .. remove item \
from channel todo list', '1) todo-chandone 2 2) todo-chandone 1 4 7')
aliases.data['chandone'] = 'todo-chandone'

def handle_todotime(bot, ievent):
    """ todo-time .. show time related todoos """
    name = users.getname(ievent.userhost)
    if not name:
        ievent.reply("can't find name of %s" % ievent.userhost)
        return
    saytodotime(bot, ievent, name)

cmnds.add('todo-time', handle_todotime, 'USER')
examples.add('todo-time', 'show todo items with time fields', 'todo-time')
aliases.data['tt'] = 'todo-time'

def handle_todoweek(bot, ievent):
    """ todo-week .. show time related todo items for this week """
    name = users.getname(ievent.userhost)
    if not name:
        ievent.reply("can't find name of %s" % ievent.userhost)
        return
    saytodotime2(bot, ievent, name, today(), today()+7*24*60*60)

cmnds.add('todo-week', handle_todoweek, 'USER')
examples.add('todo-week', 'todo items for this week', 'todo-week')

def handle_today(bot, ievent):
    """ todo-today .. show time related todo items for today """
    name = users.getname(ievent.userhost)
    if not name:
        ievent.reply("can't find name of %s" % ievent.userhost)
        return
    saytodotime2(bot, ievent, name, today(), today()+24*60*60)

cmnds.add('todo-today', handle_today, 'USER')
examples.add('todo-today', 'todo items for today', 'todo-today')
aliases.data['today'] = 'todo-today'

def toolatecheck(bot, ievent, name):
    """ check for todo items that are too late """
    nrtoolate = len(todo.toolate(name))
    if not nrtoolate:
        return
    if nrtoolate == 1:
        ievent.reply('1 item TOO LATE')
    else:
        ievent.reply(str(nrtoolate) + ' items TOO LATE')

def saytodo(bot, ievent, name):
    """ output todo items of <name> """
    res = ""
    result = todo.get(name)
    if not result:
        ievent.reply('nothing todo ;]')
        return
    for i in result:
        res += "%d) %s " % (i[0], i[5])
    ievent.reply(res)

def saytodotime(bot, ievent, name):
    """ say time related todo items of <name> """
    result = todo.get(name)
    res = ""
    now = time.time()
    for i in result:
        if not i[2]:
            continue
        if i[2] < now:
            res += 'TOO LATE: '
        ttime = time.ctime(i[2])
        res += "%s) %s %s " % (i[0], ttime, i[5])
    if res:
        ievent.reply(res)
    else:
        ievent.reply('nothing todo ;]')

def saytodotime2(bot, ievent, name, time1, time2):
    """ output todo items within time frame """
    result = todo.withintime(name, time1, time2)
    if not result:
        ievent.reply('nothing todo ;]')
        return
    now = time.time()
    res = ""
    for i in result:
        if i[2] < now:
            result += 'TOO LATE: '
        res += "%s) %s %s " % (i[0], time.ctime(i[2]), i[5])
    ievent.reply(res)
